package com.chuangke.metadata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chuangke.metadata.dao.SysBillSerialDao;
import com.chuangke.metadata.entity.SysBillSerial;
import com.chuangke.metadata.service.SysBillSerialService;

import cn.hutool.core.util.StrUtil;

import com.chuangke.common.utils.DateUtils;
import com.chuangke.common.utils.SpringContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
public class SysBillSerialServiceImpl implements SysBillSerialService {

	public static final String CACHE_REGIN = "ORDER-ID";

	@Autowired
	private SysBillSerialDao sysBillSerialDao;

	@Autowired
	private CacheManager cacheManager;
	
	@Override
	public String nextSerialId(String billKey, String scope, int length) {
		String currentSerial = nextSerial(billKey,scope) ;
		return scope+StrUtil.fillBefore(currentSerial+"",'0',length);
	}

	@Override
	public synchronized String nextSerial(String billKey, String scope) {
		synchronized(billKey){
			ValueWrapper vw = cacheManager.getCache(CACHE_REGIN).get(scope) ;
			SysBillSerial sysBillSerial;

			if (vw == null || vw.get() == null) {
				sysBillSerial = query(billKey, scope);
				if (sysBillSerial == null) {
					sysBillSerial = new SysBillSerial();
					sysBillSerial.setId(billKey+"-"+scope);
					sysBillSerial.setBillKey(billKey);
					sysBillSerial.setScope(scope);
					sysBillSerial.setSerial(1);
				}
			}else {
				sysBillSerial = (SysBillSerial)vw.get() ;
			}

			String currentSerial = sysBillSerial.getSerial() + "";

			sysBillSerial.setSerial(sysBillSerial.getSerial() + 1);

			//必须用这种方式调用，否则function调用异常
			SysBillSerialService sysBillSerialService = (SysBillSerialService) SpringContextUtil.getBean(SysBillSerialService.class) ;
			sysBillSerialService.save(sysBillSerial);

			cacheManager.getCache(CACHE_REGIN).put(scope, sysBillSerial);

			return currentSerial ;
		}
	}
	
	@Override
	public synchronized String nextSerial(String billKey) {
		String scope = billKey + DateUtils.getDate(new Date(), "yyyyMMdd");
		return nextSerial(billKey,scope) ;
	}

	@Async
	@Override
	public void save(SysBillSerial record) {
		sysBillSerialDao.saveOrUpdate(record) ;
	}

	@Override
	public SysBillSerial query(String billKey, String scope) {
		return sysBillSerialDao.getOne(new QueryWrapper<SysBillSerial>().lambda().eq(SysBillSerial::getBillKey, billKey).eq(SysBillSerial::getScope, scope));
	}

	@Override
	public void remove(List<String> ids) {
		sysBillSerialDao.remove(new QueryWrapper<SysBillSerial>().lambda().in(SysBillSerial::getBillKey,ids));
	}

	@Override
	public List<SysBillSerial> list(String billKey) {
		return sysBillSerialDao.list(new QueryWrapper<SysBillSerial>().lambda().eq(SysBillSerial::getBillKey,billKey));
	}

}
